﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NUnit.Framework;
using NHibernate;
using NHibernateSample.Domain.Entities;

namespace NHibernateSample.DAL.Test
{
    [TestFixture]
    public class TransactionSampleFixture
    {
        private ISession _session;
        private TransactionSample _tranSample;
        private NHibernateSample _sample;

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            _session = (new NHibernateHelper()).GetSession();
            HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
        }

        [SetUp]
        public void Setup()
        {
            _tranSample = new TransactionSample(_session);
            _sample = new NHibernateSample(_session);
        }

        [Test]
        public void CreateCustomerTransactionTest()
        {
            //测试成功提交
            var customer = new Customer() { FirstName = "五", LastName = "王" };
            int newIdentity = _tranSample.CreateCustomerTransaction(customer);
            var testCustomer = _sample.GetCustomerById(newIdentity);
            Assert.IsNotNull(testCustomer);
        }

        [Test]
        [ExpectedException(typeof(NHibernate.Exceptions.GenericADOException))]
        public void CreateCustomerThrowExceptionOnFailTest()
        {
            //测试失败回滚

            //设置了一个“将截断字符串或二进制数据”错误，这时必须在测试方法上指定测试预期的异常。

            //??? 为什么是"NHibernate.Exceptions.GenericADOException"异常，而非"NHibernate.HibernateException"异常 ???
            var customer = new Customer()
            {
                FirstName = "012345678901234567890123456789012345678901234567890123456789",
                LastName = "YJingLee"
            };
            _tranSample.CreateCustomerTransaction(customer);
        }

        [Test]
        public void UpdateConcurrencyViolationCanotThrowException()
        {
            //??? 为什么修改的是从c2的数据 ???
            //NHibernate: SELECT customer0_.CustomerId as CustomerId0_0_, customer0_.Version as Version0_0_, customer0_.FirstName as FirstName0_0_, customer0_.LastName as LastName0_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
            //NHibernate: UPDATE Customer SET Version = @p0, FirstName = @p1, LastName = @p2 WHERE CustomerId = @p3 AND Version = @p4;@p0 = 6, @p1 = 'www.cnblogs.com', @p2 = '李', @p3 = 1, @p4 = 5
            Customer c1 = _sample.GetCustomerById(1);
            Customer c2 = _sample.GetCustomerById(1);
            c1.FirstName = "CnBlogs";
            c2.FirstName = "www.cnblogs.com";

            _tranSample.UpdateCustomerTransaction(c1); 
            _tranSample.UpdateCustomerTransaction(c2);
        }

        [Test]
        [ExpectedException(typeof(NHibernate.StaleObjectStateException))]
        public void DeleteConcurrencyViolationCanotThrowException()
        {
            Customer c1 = _sample.GetCustomerById(15);
            Customer c2 = _sample.GetCustomerById(15);

            _tranSample.DeleteCustomerTransaction(c1);
            _tranSample.DeleteCustomerTransaction(c2);
        }

        /// <summary>
        /// NHibernate之旅(15)：探索NHibernate中使用存储过程(上)
        /// 获取一个对象；调用ISession.Delete()；同步ISession
        /// </summary>
        [Test]
        public void DeleteCustomerTest()
        {
            //存储过程执行删除或普通SQL执行删除
            //修改映射文件添加存储过程，打开Customer.hbm.xml映射文件，在Class元素下添加<sql-delete>节点，调用CustomerDelete存储过程，CustomerDelete存储过程有一个CustomerId参数，这里用一个问号表示：
            //<sql-delete>exec CustomerDelete ?</sql-delete>

            //var customerNew = new Customer() { FirstName = "五", LastName = "王" };
            //int newIdentity = _tranSample.CreateCustomerTransaction(customerNew);
            int newIdentity = 21;
            var customer = _sample.GetCustomerById(newIdentity);
            _tranSample.DeleteCustomerTransaction(customer);
            var testCustomer = _sample.GetCustomerById(newIdentity);
            Assert.IsNull(testCustomer);
        }

        /// <summary>
        /// NHibernate之旅(16)：探索NHibernate中使用存储过程(中)
        /// 新建一个对象；调用ISession.Save()；同步ISession。
        /// </summary>
        [Test]
        public void CreateCustomerTest()
        {
            //新建一个Customer对象，调用CreateCustomer()方法返回新插入的CustomerId，再次根据CustomerId查询数据库是否存在这个对象。
            var customer = new Customer() { FirstName = "三", LastName = "张", Version=1};
            int newIdentity = _tranSample.CreateCustomerTransaction(customer);
            Assert.AreEqual(37, newIdentity);
            var testCustomer = _sample.GetCustomerById(newIdentity);
            Assert.IsNotNull(testCustomer);
        }
    }
}
